package com.example.product.biz.service.impl;

import com.alibaba.fastjson.JSON;
import com.example.common.constant.MessageConstant;
import com.example.common.domain.PageResult;
import com.example.common.exception.BizIllegalException;
import com.example.product.biz.domain.dto.ProductSearchDTO;
import com.example.product.biz.domain.po.ProductDoc;
import com.example.product.biz.domain.po.ProductSku;
import com.example.product.biz.domain.po.SpecGroup;
import com.example.product.biz.domain.vo.*;
import com.example.product.biz.mapper.ProductMapper;
import com.example.product.biz.service.ProductService;
import com.example.product.domain.dto.ItemDTO;
import com.example.product.domain.po.SkuSpec;
import com.example.product.domain.vo.ProductVO;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
@RequiredArgsConstructor
public class ProductServiceImpl implements ProductService {
    private final ProductMapper productMapper;
    private final RestHighLevelClient client;
    private ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 获取商品信息
     *
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public PageResult<RecommendProductVO> getProduct(Integer page, Integer pageSize) {
        PageHelper.startPage(page, pageSize);
        Page<RecommendProductVO> pages = productMapper.selectProduct();
        return new PageResult<>(pages.getTotal(), pages.getResult());
    }

    /**
     * 根据商品id获取商品信息
     *
     * @param procuctId
     * @return
     */
    @Override
    public ProductDetailVO getProductById(Integer procuctId) {
        ProductDetailVO productDetailVO = productMapper.selectProductById(procuctId);
        if (productDetailVO == null) {
            return null;
        }
        productDetailVO.setImages(productMapper.selectImagesByProductId(procuctId));
        productDetailVO.setDetailImages(productMapper.selectDetailImages(procuctId));
        productDetailVO.setRecommendProducts(productMapper.selectProduct().getResult());

        List<ProductSpecVO> specList = new ArrayList<>();
        // 获取根据id获取该商品所有规格名称
        List<SpecGroup> nameList = productMapper.groupSpecName(procuctId);
        nameList.forEach(specGroup -> {
            List<SpecItemVO> specValue = productMapper.selectSpecBySpecGroupId(specGroup.getId());
            ProductSpecVO productSpecVO = new ProductSpecVO(specGroup.getName(), specValue);
            specList.add(productSpecVO);
        });
        // 获取商品规格信息(列表)
        productDetailVO.setProductSpecsVO(specList);


        // sku_list
        List<ProductSku> skuList = productMapper.selectSkuList(procuctId);
        List<ProductSkuVO> skuVOList = new ArrayList<>();
        // 关键配置：下划线转驼峰命名
        objectMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
        skuList.forEach(productSku -> {
            try {
                List<SkuSpec> specsList = objectMapper.readValue(
                        productSku.getSpecs(),
                        TypeFactory.defaultInstance().constructCollectionType(List.class, SkuSpec.class));
                // 存储每一个sku的规格值（颜色，尺寸....）
                List<String> list = new ArrayList<>();
                specsList.forEach(skuSpec -> {
                    list.add(productMapper.selectItemValue(skuSpec.getItemId()));
                });
                ProductSkuVO productSkuVO = new ProductSkuVO();
                BeanUtils.copyProperties(productSku, productSkuVO);
                productSkuVO.setSpecsValues(list);
                skuVOList.add(productSkuVO);
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }
        });

        productDetailVO.setProductSkuVO(skuVOList);
        return productDetailVO;
    }

    @Override
    @Transactional
    public Map<Long, ProductVO> getProductToMap(List<Long> ids) {
        Map<Long, ProductVO> map = new HashMap<>();
        for (Long itemId : ids) {
            Integer productId = productMapper.selectProductId(itemId);
            // 名称，状态
            ProductVO productVO = productMapper.selectStatusByProductId(productId);
            // productId
            productVO.setProductId(productId);
            // 价格，库存，规格
            ProductInfo productInfo = productMapper.selectProductInfo(itemId);
            // 关键配置：下划线转驼峰命名
            objectMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
            try {
                List<SkuSpec> specsList = objectMapper.readValue(
                        //[{"group_id":1,"item_id":2}]
                        productInfo.getSpecs(),
                        TypeFactory.defaultInstance().constructCollectionType(List.class, SkuSpec.class));

                // 使用 String.join() 简化代码
                List<String> specValues = new ArrayList<>();
                specsList.forEach(skuSpec -> {
                    specValues.add(productMapper.selectItemValue(skuSpec.getItemId()));
                });
                productInfo.setSpecs(String.join(",", specValues));

            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }

            BeanUtils.copyProperties(productInfo, productVO);
            map.put(itemId, productVO);
        }
        return map;
    }

    @Override
    @Transactional
    public void deductStock(List<ItemDTO> itemDTO) {
        try {
            productMapper.deductStock(itemDTO);
        } catch (Exception e) {
            throw new BizIllegalException(MessageConstant.STOCK_NOT_ENOUGH);
        }
    }

    /**
     * 恢复库存
     *
     * @param skuId
     * @param num
     */
    @Override
    public void restoreStock(Integer skuId, Integer num) {
        productMapper.restoreStock(skuId, num);
    }

    /**
     * 商品搜索
     *
     * @param searchDTO
     * @return
     */
    @Override
    public PageResult<RecommendProductVO> searchProduct(ProductSearchDTO searchDTO) {
        // 设置默认值
        if (searchDTO.getPage() == null || searchDTO.getPage() < 1) {
            searchDTO.setPage(1);
        }
        if (searchDTO.getPageSize() == null || searchDTO.getPageSize() < 1) {
            searchDTO.setPageSize(10);
        }

        // 构建 Elasticsearch 查询
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        // 关键词匹配
        if (StringUtils.hasText(searchDTO.getKeyword())) {
            boolQuery.should(QueryBuilders.matchQuery("name", searchDTO.getKeyword()))
                    .should(QueryBuilders.matchQuery("description", searchDTO.getKeyword()));
        }

        // 分类筛选
        if (searchDTO.getCategoryId() != null) {
            boolQuery.filter(QueryBuilders.termQuery("categoryId", searchDTO.getCategoryId()));
        }

        // 描述筛选
        if (StringUtils.hasText(searchDTO.getDescription())) {
            boolQuery.filter(QueryBuilders.matchQuery("description", searchDTO.getDescription()));
        }

        // 价格区间筛选
        if (searchDTO.getMinPrice() != null || searchDTO.getMaxPrice() != null) {
            RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("basePrice");
            if (searchDTO.getMinPrice() != null) {
                rangeQuery.gte(searchDTO.getMinPrice());
            }
            if (searchDTO.getMaxPrice() != null) {
                rangeQuery.lte(searchDTO.getMaxPrice());
            }
            boolQuery.filter(rangeQuery);
        }

        // 如果没有任何条件，则匹配所有
        if (!boolQuery.hasClauses()) {
            boolQuery.filter(QueryBuilders.matchAllQuery());
        }

        // 构建查询请求
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(boolQuery);
        sourceBuilder.from((searchDTO.getPage() - 1) * searchDTO.getPageSize());
        sourceBuilder.size(searchDTO.getPageSize());

        // 排序处理
        if (StringUtils.hasText(searchDTO.getSortBy())) {
            SortOrder order = SortOrder.ASC;
            if ("desc".equalsIgnoreCase(searchDTO.getSortOrder())) {
                order = SortOrder.DESC;
            }
            sourceBuilder.sort(searchDTO.getSortBy(), order);
        }

        SearchRequest searchRequest = new SearchRequest("product");
        searchRequest.source(sourceBuilder);
        try {
            // 执行查询
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

            // 处理查询结果
            SearchHits hits = searchResponse.getHits();
            List<RecommendProductVO> productList = new ArrayList<>();

            // 遍历搜索结果
            for (SearchHit hit : hits) {
                // 获取_source数据
                String sourceAsString = hit.getSourceAsString();
                // 将JSON转换为ProductDoc对象
                ProductDoc productDoc = JSON.parseObject(sourceAsString, ProductDoc.class);

                // 转换为ProductVO对象
                RecommendProductVO productVO = new RecommendProductVO();
              BeanUtils.copyProperties(productDoc, productVO);

                productList.add(productVO);
            }

            // 获取总数量
            long totalHits = hits.getTotalHits().value;

            // 返回分页结果
            return new PageResult<>(totalHits, productList);
        } catch (IOException e) {
            throw new BizIllegalException("商品搜索失败");
        }
    }


    // 批量同步方法
    public void syncAllProductsToElasticsearch() {
        try {
            // 查询所有商品
            List<ProductDoc> products = productMapper.selectAllProductsForElasticsearch();
            System.out.println("products："+products);

            // 批量索引
            BulkRequest bulkRequest = new BulkRequest();
            for (ProductDoc product : products) {
                IndexRequest indexRequest = new IndexRequest("product");
                indexRequest.id(String.valueOf(product.getId()));
                indexRequest.source(JSON.toJSONString(product), XContentType.JSON);
                bulkRequest.add(indexRequest);
            }

            // 执行批量索引
            if (!bulkRequest.requests().isEmpty()) {
                BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
                if (bulkResponse.hasFailures()) {
                    log.error("批量同步商品到 Elasticsearch 存在失败项: {}", bulkResponse.buildFailureMessage());
                }
            }
        } catch (IOException e) {
            log.error("批量同步商品到 Elasticsearch 失败", e);
            throw new BizIllegalException("数据批量同步失败");
        }
    }

}
